//
//  HHHttpCom.m
//  Pod
//
//  Created by Basic on 2017/3/11.
//  Copyright © 2017年 naruto. All rights reserved.
//  zhouhua 网络业务组件-http引擎类

#import "HHHttpCom.h"
#import "HHNetworkKitHeader.h"
#import "HHHttpConfig.h"
#import "HHHttpEnv.h"
#import <BCFileLog/BCFileLog.h>
#import <BCFoundation/BCFoundationUtils.h>
#import <BCFoundation/BCFileHelper.h>
#import <BCFoundation/UIImage+BCHelper.h>
#import <BCFoundation/UIDevice+BCHardware.h>

#define kHHHttpCom_ImageMaxLength 10000.0   //上传图片最大大小 10000kb

@interface HHHttpCom ()
@property (nonatomic, strong) dispatch_group_t uploadGroup;

@property (nonatomic, assign) BOOL enableLogs;

@property (nonatomic, strong) AFHTTPRequestSerializer * httpRequestSerializer;
@property (nonatomic, strong) AFJSONRequestSerializer * jsonRequestSerializer;

@end

@implementation HHHttpCom
//MARK: - system
+ (instancetype)shared {
    return [HHHttpCom sharedInstance];
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _enableLogs = YES;
        _httpConfig = [[HHHttpConfig alloc] init];
        //指定序列化请求数据的方式
        self.bcSessionManager.requestSerializer = self.httpRequestSerializer;
//        [self.bcSessionManager.requestSerializer setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        self.bcSessionManager.requestSerializer.timeoutInterval = 30;
        self.bcSessionManager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        self.bcSessionManager.responseSerializer.acceptableContentTypes =  [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain", @"application/xml", @"multipart/form-data", nil];
        [self.bcSessionManager.requestSerializer setValue:[UIDevice bc_platform] forHTTPHeaderField:@"deviceinfo"];
    }
    return self;
}

//MARK: - getter
- (dispatch_group_t)uploadGroup {
    if (!_uploadGroup) {
        _uploadGroup = dispatch_group_create();
    }
    return _uploadGroup;
}
- (AFHTTPRequestSerializer *)httpRequestSerializer {
    if (!_httpRequestSerializer) {
        _httpRequestSerializer = [AFHTTPRequestSerializer serializer];
        _httpRequestSerializer.timeoutInterval = 30;
        _httpRequestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    }
    return _httpRequestSerializer;
}
- (AFJSONRequestSerializer *)jsonRequestSerializer {
    if (!_jsonRequestSerializer) {
        _jsonRequestSerializer = [AFJSONRequestSerializer serializer];
        _jsonRequestSerializer.timeoutInterval = 30;
        _jsonRequestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    }
    return _jsonRequestSerializer;
}

//MARK: - 初始化
- (void)hh_setup
{
    //设置环境
    self.httpConfig.configDelegate = self.configDelegate;
    [self.httpConfig hhnet_setup:self.httpConfig];
}
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field {
    [self.httpRequestSerializer setValue:value forHTTPHeaderField:field];
    [self.jsonRequestSerializer setValue:value forHTTPHeaderField:field];
}

- (void)enableLogs:(BOOL)enable {
    _enableLogs = enable;
}

//MARK: - override 发送请求
+ (BCBaseRequestOperation *)bc_sendRequestWithURL:(NSString *)url withApi:(NSString *)api withHeaders:(NSDictionary *_Nullable)headers withParam:(NSDictionary *)param withMethod:(BCBaseRequestMethod)method withContentType:(BCRequestContentType)contentType withConstruct:(void (^)(BCHttpRequestModel *))constructAction withSuccess:(void (^)(BCBaseRequestOperation *, BCHttpResponseModel *))successAction withError:(void (^)(BCBaseRequestOperation *, BCHttpResponseModel *))errorAction withComplate:(void (^)(BCHttpRequestModel *, BCHttpResponseModel *))complate withTarget:(id)target {
    //构造 RequestModel
    BCHttpRequestModel *reqModel = [[BCHttpRequestModel alloc] initRequestWithDomain:nil withParam:param withMethod:method withSuccess:successAction withError:errorAction withTarget:target];
    reqModel.pacTag = api;
    reqModel.queueType = BCRequestQueueConcurrent;
    reqModel.customHeaders = headers;
    reqModel.timeoutInterval = 30;
    reqModel.bcComplateBlock = complate;
    reqModel.contentType = contentType;
    // 检测是否加载用户信息
    if (param[kZHNetwork_DisableUser]) {
        reqModel.addUserCookies = [param[kZHNetwork_DisableUser] boolValue];
    }
    if (param[kZHNetwork_UserAuth]) {
        reqModel.needUserAuth = [param[kZHNetwork_UserAuth] boolValue];
    }
    if (url.length > 0) {//如果指定了URL
        reqModel.requestURL = url;
        reqModel.requestHost = nil;
        reqModel.requestPath = nil;
    } else {
        //未指定url，拼接url
        reqModel.requestPath = api;
        reqModel.requestHost = HHHttpEnv.shared.apiHost;
        // 兼容api为完整url
        if ([reqModel.requestPath hasPrefix:@"http://"] ||
            [reqModel.requestPath hasPrefix:@"https://"]) {
            reqModel.requestURL = [NSString stringWithFormat:@"%@", reqModel.requestPath];
            reqModel.requestPath = nil;
        } else {
            reqModel.requestURL = [NSString stringWithFormat:@"%@/%@", HHHttpEnv.shared.httpApi_host, reqModel.requestPath];
        }
    }

    // 检测请求数据是否使用data
    if (param[kZHNetwork_InsideData]) {
        id httpData = param[kZHNetwork_InsideData];
        // 如果传入的直接是jsonString 直接赋值
        if ([httpData isKindOfClass:[NSString class]]) {
            reqModel.httpBody = httpData;
        } else { // 转成jsonString
            NSError *error;
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:httpData
                                                               options:kNilOptions
                                                                 error:&error];
            if ([jsonData length] != 0) {
                NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                reqModel.httpBody = jsonString;
            }
            if (error) {
                BCLogInfo(@"[http] request httpBody error:%@", error.localizedDescription);
            }
        }
    }

    if (constructAction) {
        constructAction(reqModel);
    }
    @BCWeakify(reqModel);
    [reqModel setConstructingBodyBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        @BCStrongify(reqModel);
        //文件上传
        if (reqModel.requestMethod == BCBaseRequestMethodFileUpload) {
            for (BCHttpFileModel *fileModel in reqModel.files) {
                if (fileModel.fileData) {
                    if (fileModel.name != nil && fileModel.name.length > 0) {
                        [formData appendPartWithFileData:fileModel.fileData name:fileModel.name fileName:fileModel.fileName mimeType:@"image/png"];
                    } else {
                        [formData appendPartWithFileData:fileModel.fileData name:@"file" fileName:fileModel.fileName mimeType:@"image/png"];
                    }
                } else if (fileModel.filePath.length > 0) {
                    [formData appendPartWithFileURL:[NSURL fileURLWithPath:fileModel.filePath] name:@"files" error:nil];
                }
            }
        }
    }];
    BCBaseRequestOperation *request = [[[self class] sharedInstance] bc_addBaseRequest:reqModel];
    //日志打印
    BOOL saveLog = ![param[kZHNetwork_NoSaveLog] boolValue];//请求是否保存日志
    if (kHHHttpComInstance.enableLogs && saveLog) {
        NSString *dicStr = nil;
        // 容错处理
        if (request.requestModel.serverPostParams) {
            NSData *dicData = [NSJSONSerialization dataWithJSONObject:request.requestModel.serverPostParams options:NSJSONWritingPrettyPrinted error:nil];
            dicStr = [[NSString alloc] initWithData:dicData encoding:NSUTF8StringEncoding];
            BCLogInfo(@"[http] request:%@,%@,%@", reqModel.finalURL, request.requestModel.headerParams, dicStr);
        }
    }
    return request;
}

//MARK: - get 请求
+ (BCBaseRequestOperation *)getURL:(NSString *)url withParam:(NSDictionary *)param withComplate:(void (^)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id)target {
    return [self hh_requestAPIWithURL:url withApi:nil withHeaders:nil withParam:param withMethod:BCBaseRequestMethodGet withContentType:BCRequestContentTypeForm withConstruct:nil withComplate:complateAction withTarget:target];
}

//MARK: - POST 请求
+ (BCBaseRequestOperation *)requestUrl:(NSString *)url withParam:(NSDictionary *)param withComplate:(void (^)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id)target {

    return [self requestURL:url withContentType:BCRequestContentTypeForm withHeaders:nil withParam:param withComplate:complateAction withTarget:target];
}

+ (BCBaseRequestOperation *)requestJsonUrl:(NSString *_Nullable)url withParam:(NSDictionary *_Nullable)param withComplate:(void (^_Nullable)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id _Nullable)target {
//    NSMutableDictionary * mHeaderParams = [[NSMutableDictionary alloc] init];
//    mHeaderParams[@"Content-Type"] = @"application/json";
    return [self requestURL:url withContentType:BCRequestContentTypeJson withHeaders:nil withParam:param withComplate:complateAction withTarget:target];
}

+ (BCBaseRequestOperation *)requestPut:(NSString *_Nullable)url withParam:(NSDictionary *_Nullable)param withComplate:(void (^_Nullable)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id _Nullable)target {
//    NSMutableDictionary * mHeaderParams = [[NSMutableDictionary alloc] init];
//    mHeaderParams[@"Content-Type"] = @"application/json";
    
    
    return [self requestURLPut:url withContentType:BCRequestContentTypeJson withHeaders:nil withParam:param withComplate:complateAction withTarget:target];
    

}




+ (BCBaseRequestOperation *)requestURL:(NSString *_Nullable)url
                       withContentType:(BCRequestContentType)contentType
                           withHeaders:(NSDictionary<NSString *, id> *_Nullable)headers withParam:(NSDictionary<NSString *, id> *_Nullable)param withComplate:(void (^_Nullable)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id _Nullable)target {
    AFHTTPSessionManager *sessionManager = BCBaseHttpEngineInstance.bcSessionManager;
    if (sessionManager.requestSerializer) {
        if (contentType == BCRequestContentTypeJson) {
            sessionManager.requestSerializer = HHHttpCom.shared.jsonRequestSerializer;
        }else{
            sessionManager.requestSerializer = HHHttpCom.shared.httpRequestSerializer;
        }
    }
    return [self hh_requestAPIWithURL:url withApi:nil withHeaders:headers withParam:param                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        withMethod:BCBaseRequestMethodPost withContentType:contentType withConstruct:nil withComplate:complateAction withTarget:target];
}

+ (BCBaseRequestOperation *)requestURLPut:(NSString *_Nullable)url
                       withContentType:(BCRequestContentType)contentType
                           withHeaders:(NSDictionary<NSString *, id> *_Nullable)headers withParam:(NSDictionary<NSString *, id> *_Nullable)param withComplate:(void (^_Nullable)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id _Nullable)target {
    AFHTTPSessionManager *sessionManager = BCBaseHttpEngineInstance.bcSessionManager;
    if (sessionManager.requestSerializer) {
        if (contentType == BCRequestContentTypeJson) {
            sessionManager.requestSerializer = HHHttpCom.shared.jsonRequestSerializer;
        }else{
            sessionManager.requestSerializer = HHHttpCom.shared.httpRequestSerializer;
        }
    }
    return [self hh_requestAPIWithURL:url withApi:nil withHeaders:headers withParam:param                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        withMethod:BCBaseRequestMethodPUT withContentType:contentType withConstruct:nil withComplate:complateAction withTarget:target];
}




+ (BCBaseRequestOperation *)requestAPI:(NSString *)api withParam:(NSDictionary *)param withComplate:(void (^)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id)target {
    return [self hh_requestAPIWithURL:nil withApi:api withHeaders:nil withParam:param withMethod:BCBaseRequestMethodPost withContentType:BCRequestContentTypeForm withConstruct:nil withComplate:complateAction withTarget:target];
}
+ (BCBaseRequestOperation *)deleteURL:(NSString *_Nullable)url withParam:(NSDictionary *_Nullable)param withComplate:(void (^_Nullable)(BCHttpRequestModel *, BCHttpResponseModel *))complateAction withTarget:(id _Nullable)target {
    return [self hh_requestAPIWithURL:url withApi:nil withHeaders:nil withParam:param withMethod:BCBaseRequestMethodDelete withContentType:BCRequestContentTypeForm withConstruct:nil withComplate:complateAction withTarget:target];
}
+ (BCBaseRequestOperation *)hh_requestAPIWithURL:(NSString *_Nullable)url withApi:(NSString *_Nullable)api withHeaders:(NSDictionary<NSString *, id> *_Nullable)headers withParam:(NSDictionary<NSString *, id> *_Nullable)param withMethod:(BCBaseRequestMethod)method withContentType:(BCRequestContentType)contentType withConstruct:(void (^_Nullable)(BCHttpRequestModel *requestModel))constructAction withComplate:(void (^_Nullable)(BCHttpRequestModel *request, BCHttpResponseModel *response))complateAction withTarget:(id _Nullable)target {
    //本地参数解析
    //请求是否显示loading
    BOOL showLoading = [param[kZHNetwork_ShowLoading] boolValue];
    //请求是否保存日志
    BOOL saveLog = ![param[kZHNetwork_NoSaveLog] boolValue];
    //错误提醒样式
    NSString *showErrorStyle = param[kZHNetwork_ShowErrorStyle];
    //请求是否隐藏errorMsg,如果为true，隐藏全部错误提示
    BOOL hideErrorMsg = NO;
    if (param[kZHNetwork_HideErrorMsg]) {
        hideErrorMsg = [param[kZHNetwork_HideErrorMsg] boolValue];
    }
    //需要隐藏errorMsg的code列表
    NSArray *hideErrorMsgCodes = (NSArray *)(param[kZHNetwork_HideErrorMsgCodes]);
    //默认错误提示
    NSString *strDefaultErrMsg = param[kZHNetwork_DefaultErrMsg];
    //alert取消提示
    NSString *alertCancelText = param[kZHNetwork_AlertCancelText];
    //成功 提示
    NSString *strSuccessMsg = param[kZHNetwork_SuccessMsg];
    if (showLoading) {
        NSString *strLoading = param[kZHNetwork_LoadingMsg];
        [kHHHttpComInstance showLoading:strLoading];
    }
    //检测mock
#ifdef DEBUG
    NSDictionary *jsonDict = [HHHttpCom loadMockJsonWithAPI:url param:param];
    if (jsonDict != nil) {
        //需要mock，构造request、response,延迟2s回调
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            BCHttpRequestModel *requestModel = [[BCHttpRequestModel alloc] initRequestWithDomain:nil withParam:param withMethod:BCBaseRequestMethodPost withSuccess:nil withError:nil withTarget:target];
            requestModel.pacTag = api;
            requestModel.queueType = BCRequestQueueConcurrent;
            requestModel.requestURL = url;
            requestModel.requestPath = api;
            requestModel.customHeaders = headers;
            [kHHHttpComInstance bc_configRequestParams:requestModel];
            BCHttpResponseModel *response = [BCHttpResponseModel yy_modelWithDictionary:jsonDict];
            response.bc_statusCode = 200;
            response.bc_data = jsonDict;
            response.success = response.code.integerValue == [kZHNetwork_CodeSuccess integerValue];

//            [kHHHttpComInstance.httpConfig hhnet_onRequestComplate:requestModel response:response];
            if (showLoading) {
                [kHHHttpComInstance hideLoading];
            }
            if (complateAction) {
                complateAction(requestModel, response);
            }
        });
        return nil;
    }
#endif
    //发送请求
    BCBaseRequestOperation *requestOperation = [[self class] bc_sendRequestWithURL:url withApi:api withHeaders:headers withParam:param withMethod:method withContentType:contentType withConstruct:constructAction withSuccess:^(BCBaseRequestOperation *request, BCHttpResponseModel *response) {
        //        @BCStrongObj(self);
        if (showLoading) {
            [kHHHttpComInstance hideLoading];
        }
        //判断网络成功
        response.success = response.code.integerValue == [kZHNetwork_CodeSuccess integerValue];
        //日志打印
        if (kHHHttpComInstance.enableLogs && saveLog) {
            NSString *dicStr = nil;
            NSData *dicData = [NSJSONSerialization dataWithJSONObject:response.bc_data options:NSJSONWritingPrettyPrinted error:nil];
            dicStr = [[NSString alloc] initWithData:dicData encoding:NSUTF8StringEncoding];
            if (url.length > 0) {
                BCLogInfo(@"[http] response:%@,%@", url, dicStr);
            } else {
                BCLogInfo(@"[http] response:%@,%@", request.requestModel.requestPath, dicStr);
            }
        }
        //数据处理
        if (response.success) {
            //请求成功
            if (strSuccessMsg.length > 0) {
                response.popup.message = strSuccessMsg;
            }
        } else {
            //请求失败
            BCHttpResponseMsgModel *tmpPopup =  response.popup;
            tmpPopup.message = response.message;
            if(tmpPopup.buttonNameList.count == 0) {
                NSString *cancelText = alertCancelText?:BCLOC(@"确定");
                tmpPopup.buttonNameList = @[cancelText];
            }

            if (!hideErrorMsg) {
                if (hideErrorMsgCodes != nil && response.code && [hideErrorMsgCodes containsObject:response.code]) {
                    //当前code需要隐藏
                    tmpPopup.type = kBCHttpResponse_MsgTypeNone;
                } else {
                    //当前code不需要隐藏
                    if(tmpPopup.type == 0) {
                        //指定错误样式
                        if (showErrorStyle.length > 0) {
                            tmpPopup.type = kBCHttpResponse_MsgTypeAlert;
                        } else {
                            tmpPopup.type = kBCHttpResponse_MsgTypeToast;
                        }
                    }
                    //处理默认错误提示
                    if (strDefaultErrMsg.length > 0 && response.popup.message.length <= 0) {
                        response.popup.message = strDefaultErrMsg;
                    }
                }
            } else {
                //隐藏错误提示
                response.popup.type = kBCHttpResponse_MsgTypeNone;
            }
        }
        // 统一拦截x
        [kHHHttpComInstance.httpConfig hhnet_onRequestComplate:request.requestModel response:response];

        // 单个回调
        if (complateAction) {
            complateAction(request.requestModel, response);
        }
    } withError:^(BCBaseRequestOperation *request, BCHttpResponseModel *response) {
        if (showLoading) {
            [kHHHttpComInstance hideLoading];
        }
        //日志打印
        if (kHHHttpComInstance.enableLogs && saveLog) {
            BCLogInfo(@"[http] response err:%@,%@", request.requestModel.requestURL, response.bc_error);
        }
        //数据处理
        [response bc_loadDefaultResponse];
        if (response.message) {
            response.popup.message = response.message;
        }
        if (!hideErrorMsg) {
            //指定错误样式
            if (showErrorStyle.length > 0) {
                response.popup.type = kBCHttpResponse_MsgTypeAlert;
                response.popup.buttonNameList = @[BCLOC(@"确定")];
            }
        } else {
            //隐藏错误提示
            response.popup.type = kBCHttpResponse_MsgTypeNone;
        }

        // 统一拦截
        [kHHHttpComInstance.httpConfig hhnet_onRequestComplate:request.requestModel response:response];

        // 单个回调
        if (complateAction) {
            complateAction(request.requestModel, response);
        }
    } withComplate:complateAction withTarget:target];
    
    return requestOperation;
}

//MARK: - 上传文件请求 - http 上传
+ (void)uploadImage:(UIImage *)image progress:(void (^_Nullable)(float percent))uploadProgress complete:(void (^_Nullable)(BOOL success, NSString *imageUrl))complete {
    if (!image) {
        return;
    }
    BCHttpFileModel *tmpfileModel = [[BCHttpFileModel alloc] init];
    tmpfileModel.fileName = [NSString stringWithFormat:@"%@.jpg", @(time(NULL) * 1000)];
    tmpfileModel.fileData = UIImageJPEGRepresentation(image, 0.5);

    [self uploadWithFile:tmpfileModel progress:uploadProgress complete:^(BCHttpResponseModel *_Nonnull response, BCHttpFileModel *_Nonnull fileModel) {
        if (complete) {
            complete(response.success, fileModel.fileURL);
        }
    }];
}

+ (void)uploadFileWithPath:(NSString *)filePath progress:(void (^_Nullable)(float percent))uploadProgress complete:(void (^_Nullable)(BOOL success, NSString *filePath, NSString *fileURL))complete {
    if (filePath.length < 1) {
        return;
    }
    BCHttpFileModel *tmpfileModel = [[BCHttpFileModel alloc] init];
    tmpfileModel.fileName = filePath.lastPathComponent;
    tmpfileModel.filePath = filePath;

    [self uploadWithFile:tmpfileModel progress:uploadProgress complete:^(BCHttpResponseModel *_Nonnull response, BCHttpFileModel *_Nonnull fileModel) {
        if (complete) {
            complete(response.success, fileModel.filePath, fileModel.fileURL);
        }
    }];
}

+ (void)uploadWithFile:(BCHttpFileModel *)fileModel progress:(void (^_Nullable)(float percent))uploadProgress complete:(void (^_Nullable)(BCHttpResponseModel *response, BCHttpFileModel *fileModel))complete {
    [self uploadWithFiles:@[fileModel] progress:uploadProgress complete:^(BCHttpResponseModel *_Nonnull response, NSArray<BCHttpFileModel *> *_Nonnull fileModels) {
        if (complete) {
            complete(response, fileModel);
        }
    }];
}

+ (void)uploadWithFiles:(NSArray<BCHttpFileModel *> *)fileModels progress:(void (^_Nullable)(float percent))uploadProgress complete:(void (^_Nullable)(BCHttpResponseModel *response, NSArray<BCHttpFileModel *> *fileModels))complete {
    NSString *uploadURL = [NSString stringWithFormat:@"%@", HHHttpEnv.shared.httpApi_fileHost];

    NSDictionary *params = @{ @"region": @"oss-cn-hangzhou" ,
                              @"bucket":@"demo-java",
                              @"AccessKeySecret":@"e39JXDUsaQ8uIyskER0AyOdf9MvuFd",
                              @"OSSAccessKeyId":@"LTAI5tFwyRcJaqK2USpZ8UUZ"};

    [self requestUploadFilesURL:uploadURL withFileModels:fileModels withParams:params withProgress:uploadProgress withComplate:^(BCHttpRequestModel *request, BCHttpResponseModel *response, NSArray<BCHttpFileModel *> *fileModels) {
        if (complete) {
            complete(response, fileModels);
        }
    }];
}

+ (void)requestUploadFileURL:(NSString *)uploadURL withFileModel:(BCHttpFileModel *)fileModel withParams:(NSDictionary *_Nullable)params withProgress:(void (^)(float))uploadProgress withComplate:(void (^)(BCHttpRequestModel *_Nonnull, BCHttpResponseModel *_Nonnull, BCHttpFileModel *_Nonnull))complete {
    [self requestUploadFilesURL:uploadURL withFileModels:@[fileModel] withParams:params withProgress:uploadProgress withComplate:^(BCHttpRequestModel *request, BCHttpResponseModel *response, NSArray<BCHttpFileModel *> *fileModels) {
        if (complete) {
            complete(request, response, fileModels.firstObject);
        }
    }];
}

+ (void)requestUploadFilesURL:(NSString *_Nullable)uploadURL withFileModels:(NSArray<BCHttpFileModel *> *)fileModels withParams:(NSDictionary *_Nullable)params withProgress:(void (^_Nullable)(float))uploadProgress withComplate:(void (^_Nullable)(BCHttpRequestModel *request, BCHttpResponseModel *response, NSArray<BCHttpFileModel *> *fileModels))complete {
    //参数校验
    if (uploadURL.length <= 0 || fileModels.count == 0) {
        if (complete) {
            complete([[BCHttpRequestModel alloc] init], [[BCHttpResponseModel alloc] init], fileModels);
        }
        return;
    }
    //开始上传
    BCBaseHttpEngineInstance.bcSessionManager.requestSerializer = HHHttpCom.shared.httpRequestSerializer;
    [[self class] hh_requestAPIWithURL:uploadURL withApi:nil withHeaders:nil withParam:params withMethod:BCBaseRequestMethodFileUpload withContentType:BCRequestContentTypeForm withConstruct:^(BCHttpRequestModel *requestModel) {
        //文件请求参数
        requestModel.requestMethod = BCBaseRequestMethodFileUpload;
        requestModel.files = fileModels;
        requestModel.addUserCookies = YES;//需要添加cookies
        requestModel.pacTag = kZHNetworkTag_FileUpload;
    } withComplate:^(BCHttpRequestModel *request, BCHttpResponseModel *response) {
        if (complete) {
            complete(request, response, fileModels);
        }
    } withTarget:self];
}

//MARK: - override
- (void)bc_configRequestParams:(BCHttpRequestModel *)request {
    [self.httpConfig hhnet_willSendRequest:request];
}

//MARK: - 错误消息处理
- (void)showLoading:(NSString *)msg {
    [self.httpConfig hhnet_showLoading:msg];
}

- (void)showSuccessMsg:(NSString *)msg {
    [self.httpConfig hhnet_showSuccessMsg:msg];
}

- (void)hideLoading {
    [self.httpConfig hhnet_hideLoading];
}

- (void)handleErrorMsg:(BCHttpResponseModel *)response {
    [self.httpConfig hhnet_handleErrorMsg:response];
}

//MARK: - utils

/// 加载mock的json
/// @param api 请求的api
+ (NSDictionary *_Nullable)loadMockJsonWithAPI:(NSString *_Nonnull)api param:(NSDictionary *_Nullable)param {
    NSError *error = nil;
    NSMutableArray *mComponentaArr = [[api pathComponents] mutableCopy];
    NSMutableString *apiName = [NSMutableString string];
    NSInteger maxNum = 2;
    while (mComponentaArr.count > 0 && maxNum > 0) {
        NSString *lastComponent = mComponentaArr.lastObject;
        NSArray *separatedArr = [lastComponent componentsSeparatedByString:@"?"];
        [apiName appendFormat:@".%@",[separatedArr firstObject]];
        [mComponentaArr removeLastObject];
        maxNum --;
    }
    if (param[@"page"]) {
        [apiName appendFormat:@"%@",param[@"page"]];
    }
    NSString *bundlePath = [NSString stringWithFormat:@"mock%@", apiName];
    NSString *filePath = [[NSBundle mainBundle] pathForResource:bundlePath ofType:@"json"];
    NSData *data =  [[NSData alloc] initWithContentsOfFile:filePath];
    if (data == nil) {
        return nil;
    }
    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    if (error) {
#ifdef DEBUG
        NSLog(@"[http] load mock json error,%@,%@", api, error);
#endif
    }
    return json;
}

@end
